#include <iostream>
#include <memory>
#include <string>
#include <list>

using namespace std;

/*
\ brief:  服务接口
\ author: 清晨与猫鱼
*/
class Service {
public:
    virtual string getName() = 0;
    virtual void execute() = 0;
};


/*
\ brief:  服务1
\ author: 清晨与猫鱼
*/
class Service1 
    : public Service {
public:

    void execute() {
        cout << "Executing Service1" << endl;
    }

    string getName() {
        return "SERVICE1";
    }
};


/*
\ brief:  服务2
\ author: 清晨与猫鱼
*/
class Service2 
    : public Service {
public:

    void execute() {
        cout << "Executing Service2" << endl;
    }

    string getName() {
        return "SERVICE2";
    }
};



/*
\ brief:  初始化上下文
\ author: 清晨与猫鱼
*/
class InitialContext {
public:
    static Service* lookup(string jndiName) {
        if (jndiName == "SERVICE1") {
            cout << "Looking up and creating a new Service1 object" << endl;
            return new Service1;
        }else if (jndiName == "SERVICE2") {
            cout << "Looking up and creating a new Service2 object" << endl;
            return new Service2;
        }

        return nullptr;
    }
};




/*
\ brief:  缓存
\ author: 清晨与猫鱼
*/
class Cache {
public:

    Service* getService(string serviceName) {
        for (unique_ptr<Service>& service : services_) {
            if (service->getName() == serviceName) {
                cout << "Returning cached  " << serviceName << " object" << endl;
                return service.get();
            }
        }

        return nullptr;
    }

     void addService(Service* newService) {
        bool exists(false);
        for (unique_ptr<Service>& service : services_) {
            if (service->getName() == newService->getName()) {
                exists = true;
                break;
            }
        }

        if (!exists) {
            services_.emplace_back(newService);
        }else {
            unique_ptr<Service> ptr(newService);
        }
     }
private:
    list<unique_ptr<Service>> services_;
};



/*
\ brief:   本地缓存
\ author: 清晨与猫鱼
*/
class ServiceLocator {
public:
    static Service* getService(string jndiName) {
        Service* service = ServiceLocator::cache_.getService(jndiName);

        if (service != nullptr) {
            return service;
        }

        Service* service1 = InitialContext::lookup(jndiName);

        ServiceLocator::cache_.addService(service1);

        return service1;
    }
private:
    static Cache cache_;
};


Cache ServiceLocator::cache_;       // 初始化